home *** CD-ROM | disk | FTP | other *** search
/ Aminet 25 / Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso / Aminet / game / shoot / ADoom_src_1_2.lha / ADoom_src / r_draw.c < prev    next >
C/C++ Source or Header  |  1998-02-16  |  25KB  |  1,184 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    The actual span/column drawing functions.
  21. //    Here find the main potential for optimization,
  22. //     e.g. inline assembly, different algorithms.
  23. //
  24. //-----------------------------------------------------------------------------
  25.  
  26.  
  27. static const char
  28. rcsid[] = "$Id: r_draw.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
  29.  
  30.  
  31. #include "doomdef.h"
  32.  
  33. #include "i_system.h"
  34. #include "i_video.h"
  35. #include "z_zone.h"
  36. #include "w_wad.h"
  37.  
  38. #include "r_local.h"
  39.  
  40. // Needs access to LFB (guess what).
  41. #include "v_video.h"
  42.  
  43. // State.
  44. #include "doomstat.h"
  45.  
  46.  
  47. // ?
  48. //#define MAXWIDTH            1120
  49. //#define MAXHEIGHT            832
  50.  
  51. // status bar height at bottom of screen
  52. #define SBARHEIGHT        32
  53.  
  54. //
  55. // All drawing to the view buffer is accomplished in this file.
  56. // The other refresh files only know about ccordinates,
  57. //  not the architecture of the frame buffer.
  58. // Conveniently, the frame buffer is a linear one,
  59. //  and we need only the base address,
  60. //  and the total size == width*height*depth/8.,
  61. //
  62.  
  63.  
  64. byte*        viewimage; 
  65. int        viewwidth;
  66. int        scaledviewwidth;
  67. int        viewheight;
  68. int        viewwindowx;
  69. int        viewwindowy; 
  70. //byte*        ylookup[MAXHEIGHT]; 
  71. //byte*        ylookup2[MAXHEIGHT]; 
  72. //int        columnofs[MAXWIDTH]; 
  73. byte*        *ylookup; 
  74. byte*        *ylookup2;
  75. int        *columnofs;
  76.  
  77. // Color tables for different players,
  78. //  translate a limited part to another
  79. //  (color ramps used for  suit colors).
  80. //
  81. FAR byte    translations[3][256];    
  82.  
  83.  
  84.  
  85. //
  86. // Spectre/Invisibility.
  87. //
  88. #define FUZZTABLE       50
  89. #define FUZZOFF    (1)
  90.  
  91. int    fuzzoffset_init[FUZZTABLE] =
  92. {
  93.     FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  94.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  95.     FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
  96.     FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  97.     FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
  98.     FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
  99.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF 
  100. };
  101.  
  102. int    *fuzzoffset;
  103. int    fuzzpos = 0; 
  104.  
  105. void init_r_draw (void);
  106.  
  107. void resinit_r_draw (void)
  108. {
  109.   int i;
  110.  
  111.   ylookup = (byte **)I_malloc (SCREENHEIGHT * sizeof(byte *));
  112.   ylookup2 = (byte **)I_malloc (SCREENHEIGHT * sizeof(byte *));
  113.   columnofs = (int *)I_malloc (SCREENWIDTH * sizeof(int));
  114.  
  115.   fuzzoffset = I_malloc ((SCREENHEIGHT + 50) * sizeof(int));
  116.   for (i = 0; i < SCREENHEIGHT + 50; i++)
  117.     fuzzoffset[i] = fuzzoffset_init[i % FUZZTABLE] * SCREENWIDTH;
  118.   fuzzpos=0;
  119.  
  120.   init_r_draw ();
  121. }
  122.  
  123.  
  124.  
  125. //
  126. // R_DrawColumn
  127. // Source is the top of the column to scale.
  128. //
  129. lighttable_t*        dc_colormap; 
  130. int            dc_x; 
  131. int            dc_yl; 
  132. int            dc_yh; 
  133. fixed_t            dc_iscale; 
  134. fixed_t            dc_texturemid;
  135.  
  136. // first pixel in a column (possibly virtual) 
  137. byte*            dc_source;        
  138.  
  139. // just for profiling 
  140. int            dccount;
  141.  
  142. //
  143. // A column is a vertical slice/span from a wall texture that,
  144. //  given the DOOM style restrictions on the view orientation,
  145. //  will always have constant z depth.
  146. // Thus a special case loop for very fast rendering can
  147. //  be used. It has also been used with Wolfenstein 3D.
  148. // 
  149. // UNUSED.
  150. #ifndef AMIGA
  151. void R_DrawColumn (void) 
  152.     int            count; 
  153.     byte*        dest; 
  154.     fixed_t        frac;
  155.     fixed_t        fracstep;     
  156.  
  157.     count = dc_yh - dc_yl; 
  158.  
  159.     // Zero length, column does not exceed a pixel.
  160.     if (count < 0) 
  161.     return; 
  162.                  
  163. #ifdef RANGECHECK 
  164.     if ((unsigned)dc_x >= SCREENWIDTH
  165.     || dc_yl < 0
  166.     || dc_yh >= SCREENHEIGHT) 
  167.     I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); 
  168. #endif 
  169.  
  170.     // Framebuffer destination address.
  171.     // Use ylookup LUT to avoid multiply with ScreenWidth.
  172.     // Use columnofs LUT for subwindows? 
  173. //    dest = ylookup[dc_yl] + columnofs[dc_x];  
  174.     dest = ylookup2[dc_yl] + dc_x;
  175.  
  176.     // Determine scaling,
  177.     //  which is the only mapping to be done.
  178.     fracstep = dc_iscale; 
  179.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  180.  
  181.     // Inner loop that does the actual texture mapping,
  182.     //  e.g. a DDA-lile scaling.
  183.     // This is as fast as it gets.
  184.     do 
  185.     {
  186.     // Re-map color indices from wall texture column
  187.     //  using a lighting/special effects LUT.
  188.     *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
  189.     
  190.     dest += SCREENWIDTH; 
  191.     frac += fracstep;
  192.     
  193.     } while (count--); 
  194. #endif
  195.  
  196. //void R_DrawColumn_040 (void)
  197. //{
  198. //  R_DrawColumn ();
  199. //}
  200. //
  201. //void R_DrawColumn_060 (void)
  202. //{
  203. //  R_DrawColumn ();
  204. //}
  205.  
  206. // UNUSED.
  207. // Loop unrolled.
  208. #if 0
  209. void R_DrawColumn (void) 
  210.     int            count; 
  211.     byte*        source;
  212.     byte*        dest;
  213.     byte*        colormap;
  214.     
  215.     unsigned        frac;
  216.     unsigned        fracstep;
  217.     unsigned        fracstep2;
  218.     unsigned        fracstep3;
  219.     unsigned        fracstep4;     
  220.  
  221.     count = dc_yh - dc_yl + 1; 
  222.  
  223.     source = dc_source;
  224.     colormap = dc_colormap;         
  225.     dest = ylookup[dc_yl] + columnofs[dc_x];  
  226.      
  227.     fracstep = dc_iscale<<9; 
  228.     frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; 
  229.  
  230.     fracstep2 = fracstep+fracstep;
  231.     fracstep3 = fracstep2+fracstep;
  232.     fracstep4 = fracstep3+fracstep;
  233.     
  234.     while (count >= 8) 
  235.     { 
  236.     dest[0] = colormap[source[frac>>25]]; 
  237.     dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; 
  238.     dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; 
  239.     dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]];
  240.     
  241.     frac += fracstep4; 
  242.  
  243.     dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; 
  244.     dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; 
  245.     dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; 
  246.     dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; 
  247.  
  248.     frac += fracstep4; 
  249.     dest += SCREENWIDTH*8; 
  250.     count -= 8;
  251.     } 
  252.     
  253.     while (count > 0)
  254.     { 
  255.     *dest = colormap[source[frac>>25]]; 
  256.     dest += SCREENWIDTH; 
  257.     frac += fracstep; 
  258.     count--;
  259.     } 
  260. }
  261. #endif
  262.  
  263.  
  264. #ifndef AMIGA
  265. void R_DrawColumnLow (void) 
  266.     int            count; 
  267.     byte*        dest; 
  268.     byte*        dest2;
  269.     fixed_t        frac;
  270.     fixed_t        fracstep;     
  271.  
  272.     count = dc_yh - dc_yl; 
  273.  
  274.     // Zero length.
  275.     if (count < 0) 
  276.     return; 
  277.                  
  278. #ifdef RANGECHECK 
  279.     if ((unsigned)dc_x >= SCREENWIDTH
  280.     || dc_yl < 0
  281.     || dc_yh >= SCREENHEIGHT)
  282.     {
  283.     
  284.     I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
  285.     }
  286.     //    dccount++; 
  287. #endif 
  288.     // Blocky mode, need to multiply by 2.
  289.     dc_x <<= 1;
  290.     
  291.     dest = ylookup[dc_yl] + columnofs[dc_x];
  292.     dest2 = ylookup[dc_yl] + columnofs[dc_x+1];
  293.     
  294.     fracstep = dc_iscale; 
  295.     frac = dc_texturemid + (dc_yl-centery)*fracstep;
  296.     
  297.     do 
  298.     {
  299.     // Hack. Does not work corretly.
  300.     *dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
  301.     dest += SCREENWIDTH;
  302.     dest2 += SCREENWIDTH;
  303.     frac += fracstep; 
  304.  
  305.     } while (count--);
  306. }
  307. #endif
  308.  
  309.  
  310.  
  311.  
  312. #ifndef AMIGA
  313.  
  314. //
  315. // Framebuffer postprocessing.
  316. // Creates a fuzzy image by copying pixels
  317. //  from adjacent ones to left and right.
  318. // Used with an all black colormap, this
  319. //  could create the SHADOW effect,
  320. //  i.e. spectres and invisible players.
  321. //
  322. void R_DrawFuzzColumn (void) 
  323.     int            count; 
  324.     byte*        dest; 
  325.     fixed_t        frac;
  326.     fixed_t        fracstep;     
  327.  
  328.     // Adjust borders. Low... 
  329.     if (!dc_yl) 
  330.     dc_yl = 1;
  331.  
  332.     // .. and high.
  333.     if (dc_yh == viewheight-1) 
  334.     dc_yh = viewheight - 2; 
  335.          
  336.     count = dc_yh - dc_yl; 
  337.  
  338.     // Zero length.
  339.     if (count < 0) 
  340.     return; 
  341.  
  342.     
  343. #ifdef RANGECHECK 
  344.     if ((unsigned)dc_x >= SCREENWIDTH
  345.     || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
  346.     {
  347.     I_Error ("R_DrawFuzzColumn: %i to %i at %i",
  348.          dc_yl, dc_yh, dc_x);
  349.     }
  350. #endif
  351.  
  352.  
  353.     // Keep till detailshift bug in blocky mode fixed,
  354.     //  or blocky mode removed.
  355.     /* WATCOM code 
  356.     if (detailshift)
  357.     {
  358.     if (dc_x & 1)
  359.     {
  360.         outpw (GC_INDEX,GC_READMAP+(2<<8) ); 
  361.         outp (SC_INDEX+1,12); 
  362.     }
  363.     else
  364.     {
  365.         outpw (GC_INDEX,GC_READMAP); 
  366.         outp (SC_INDEX+1,3); 
  367.     }
  368.     dest = destview + dc_yl*80 + (dc_x>>1); 
  369.     }
  370.     else
  371.     {
  372.     outpw (GC_INDEX,GC_READMAP+((dc_x&3)<<8) ); 
  373.     outp (SC_INDEX+1,1<<(dc_x&3)); 
  374.     dest = destview + dc_yl*80 + (dc_x>>2); 
  375.     }*/
  376.  
  377.     
  378.     // Does not work with blocky mode.
  379.     dest = ylookup[dc_yl] + columnofs[dc_x];
  380.  
  381.     // Looks familiar.
  382.     fracstep = dc_iscale; 
  383.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  384.  
  385.     // Looks like an attempt at dithering,
  386.     //  using the colormap #6 (of 0-31, a bit
  387.     //  brighter than average).
  388.     do 
  389.     {
  390.     // Lookup framebuffer, and retrieve
  391.     //  a pixel that is either one column
  392.     //  left or right of the current one.
  393.     // Add index from colormap to index.
  394.     *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]]; 
  395.  
  396.     // Clamp table lookup index.
  397.     if (++fuzzpos == FUZZTABLE) 
  398.         fuzzpos = 0;
  399.     
  400.     dest += SCREENWIDTH;
  401.  
  402.     frac += fracstep; 
  403.     } while (count--); 
  404. #endif
  405.  
  406.   
  407.  
  408.  
  409. #ifndef AMIGA
  410.  
  411. //
  412. // Framebuffer postprocessing.
  413. // Creates a fuzzy image by copying pixels
  414. //  from adjacent ones to left and right.
  415. // Used with an all black colormap, this
  416. //  could create the SHADOW effect,
  417. //  i.e. spectres and invisible players.
  418. //
  419. void R_DrawFuzzColumnLow (void) 
  420.     int            count; 
  421.     byte*        dest; 
  422.     byte*        dest2; 
  423.     fixed_t        frac;
  424.     fixed_t        fracstep;     
  425.  
  426.     // Adjust borders. Low... 
  427.     if (!dc_yl) 
  428.     dc_yl = 1;
  429.  
  430.     // .. and high.
  431.     if (dc_yh == viewheight-1) 
  432.     dc_yh = viewheight - 2; 
  433.          
  434.     count = dc_yh - dc_yl; 
  435.  
  436.     // Zero length.
  437.     if (count < 0) 
  438.     return; 
  439.  
  440.     
  441. #ifdef RANGECHECK 
  442.     if (((unsigned)dc_x << 1) >= SCREENWIDTH
  443.     || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
  444.     {
  445.     I_Error ("R_DrawFuzzColumn: %i to %i at %i",
  446.          dc_yl, dc_yh, dc_x);
  447.     }
  448. #endif
  449.  
  450.  
  451.     // Does not work with blocky mode.
  452.     dest = ylookup[dc_yl] + columnofs[dc_x << 1];
  453.     dest2 = ylookup[dc_yl] + columnofs[(dc_x << 1) + 1];
  454.  
  455.     // Looks familiar.
  456.     fracstep = dc_iscale;
  457.     frac = dc_texturemid + (dc_yl-centery)*fracstep;
  458.  
  459.     // Looks like an attempt at dithering,
  460.     //  using the colormap #6 (of 0-31, a bit
  461.     //  brighter than average).
  462.     do 
  463.     {
  464.     // Lookup framebuffer, and retrieve
  465.     //  a pixel that is either one column
  466.     //  left or right of the current one.
  467.     // Add index from colormap to index.
  468.     *dest2 = *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
  469.  
  470.     // Clamp table lookup index.
  471.     if (++fuzzpos == FUZZTABLE)
  472.         fuzzpos = 0;
  473.  
  474.     dest += SCREENWIDTH;
  475.     dest2 += SCREENWIDTH;
  476.  
  477.     frac += fracstep;
  478.     } while (count--);
  479. }
  480. #endif
  481.  
  482.   
  483.  
  484.  
  485. //
  486. // R_DrawTranslatedColumn
  487. // Used to draw player sprites
  488. //  with the green colorramp mapped to others.
  489. // Could be used with different translation
  490. //  tables, e.g. the lighter colored version
  491. //  of the BaronOfHell, the HellKnight, uses
  492. //  identical sprites, kinda brightened up.
  493. //
  494. byte*    dc_translation;
  495. byte*    translationtables;
  496.  
  497. //#ifndef AMIGA
  498.  
  499. void R_DrawTranslatedColumn (void) 
  500.     int            count; 
  501.     byte*        dest; 
  502.     fixed_t        frac;
  503.     fixed_t        fracstep;     
  504.  
  505.     count = dc_yh - dc_yl; 
  506.     if (count < 0) 
  507.     return; 
  508.                  
  509. #ifdef RANGECHECK 
  510.     if ((unsigned)dc_x >= SCREENWIDTH
  511.     || dc_yl < 0
  512.     || dc_yh >= SCREENHEIGHT)
  513.     {
  514.     I_Error ( "R_DrawColumn: %i to %i at %i",
  515.           dc_yl, dc_yh, dc_x);
  516.     }
  517.     
  518. #endif 
  519.  
  520.  
  521.     // WATCOM VGA specific.
  522.     /* Keep for fixing.
  523.     if (detailshift)
  524.     {
  525.     if (dc_x & 1)
  526.         outp (SC_INDEX+1,12); 
  527.     else
  528.         outp (SC_INDEX+1,3);
  529.     
  530.     dest = destview + dc_yl*80 + (dc_x>>1); 
  531.     }
  532.     else
  533.     {
  534.     outp (SC_INDEX+1,1<<(dc_x&3)); 
  535.  
  536.     dest = destview + dc_yl*80 + (dc_x>>2); 
  537.     }*/
  538.  
  539.     
  540.     // FIXME. As above.
  541.     dest = ylookup[dc_yl] + columnofs[dc_x]; 
  542.  
  543.     // Looks familiar.
  544.     fracstep = dc_iscale; 
  545.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  546.  
  547.     // Here we do an additional index re-mapping.
  548.     do 
  549.     {
  550.     // Translation tables are used
  551.     //  to map certain colorramps to other ones,
  552.     //  used with PLAY sprites.
  553.     // Thus the "green" ramp of the player 0 sprite
  554.     //  is mapped to gray, red, black/indigo. 
  555.     *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
  556.     dest += SCREENWIDTH;
  557.     
  558.     frac += fracstep; 
  559.     } while (count--); 
  560.  
  561. //#endif
  562.  
  563.  
  564.  
  565. //
  566. // R_DrawTranslatedColumn
  567. // Used to draw player sprites
  568. //  with the green colorramp mapped to others.
  569. // Could be used with different translation
  570. //  tables, e.g. the lighter colored version
  571. //  of the BaronOfHell, the HellKnight, uses
  572. //  identical sprites, kinda brightened up.
  573. //
  574. byte*    dc_translation;
  575. byte*    translationtables;
  576.  
  577. //#ifndef AMIGA
  578.  
  579. void R_DrawTranslatedColumnLow (void) 
  580.     int            count; 
  581.     byte*        dest; 
  582.     byte*        dest2;
  583.     fixed_t        frac;
  584.     fixed_t        fracstep;     
  585.  
  586.     count = dc_yh - dc_yl; 
  587.     if (count < 0) 
  588.     return; 
  589.                  
  590. #ifdef RANGECHECK 
  591.     if (((unsigned)dc_x << 1) >= SCREENWIDTH
  592.     || dc_yl < 0
  593.     || dc_yh >= SCREENHEIGHT)
  594.     {
  595.     I_Error ( "R_DrawColumn: %i to %i at %i",
  596.           dc_yl, dc_yh, dc_x);
  597.     }
  598.     
  599. #endif 
  600.  
  601.  
  602.     // FIXME. As above.
  603.     dest = ylookup[dc_yl] + columnofs[dc_x << 1]; 
  604.     dest2 = ylookup[dc_yl] + columnofs[(dc_x << 1) + 1];
  605.  
  606.     // Looks familiar.
  607.     fracstep = dc_iscale; 
  608.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  609.  
  610.     // Here we do an additional index re-mapping.
  611.     do 
  612.     {
  613.     // Translation tables are used
  614.     //  to map certain colorramps to other ones,
  615.     //  used with PLAY sprites.
  616.     // Thus the "green" ramp of the player 0 sprite
  617.     //  is mapped to gray, red, black/indigo. 
  618.     *dest2 = *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
  619.     dest += SCREENWIDTH;
  620.     dest2 += SCREENWIDTH;
  621.     
  622.     frac += fracstep; 
  623.     } while (count--); 
  624.  
  625. //#endif
  626.  
  627.  
  628.  
  629. //
  630. // R_InitTranslationTables
  631. // Creates the translation tables to map
  632. //  the green color ramp to gray, brown, red.
  633. // Assumes a given structure of the PLAYPAL.
  634. // Could be read from a lump instead.
  635. //
  636. void R_InitTranslationTables (void)
  637. {
  638.     int        i;
  639.     
  640.     translationtables = Z_Malloc (256*3+255, PU_STATIC, 0);
  641.     translationtables = (byte *)(( (int)translationtables + 255 )& ~255);
  642.     
  643.     // translate just the 16 green colors
  644.     for (i=0 ; i<256 ; i++)
  645.     {
  646.     if (i >= 0x70 && i<= 0x7f)
  647.     {
  648.         // map green ramp to gray, brown, red
  649.         translationtables[i] = 0x60 + (i&0xf);
  650.         translationtables [i+256] = 0x40 + (i&0xf);
  651.         translationtables [i+512] = 0x20 + (i&0xf);
  652.     }
  653.     else
  654.     {
  655.         // Keep all other colors as is.
  656.         translationtables[i] = translationtables[i+256] 
  657.         = translationtables[i+512] = i;
  658.     }
  659.     }
  660. }
  661.  
  662.  
  663.  
  664.  
  665. //
  666. // R_DrawSpan 
  667. // With DOOM style restrictions on view orientation,
  668. //  the floors and ceilings consist of horizontal slices
  669. //  or spans with constant z depth.
  670. // However, rotation around the world z axis is possible,
  671. //  thus this mapping, while simpler and faster than
  672. //  perspective correct texture mapping, has to traverse
  673. //  the texture at an angle in all but a few cases.
  674. // In consequence, flats are not stored by column (like walls),
  675. //  and the inner loop has to step in texture space u and v.
  676. //
  677. int            ds_y; 
  678. int            ds_x1; 
  679. int            ds_x2;
  680.  
  681. lighttable_t*        ds_colormap; 
  682.  
  683. fixed_t            ds_xfrac; 
  684. fixed_t            ds_yfrac; 
  685. fixed_t            ds_xstep; 
  686. fixed_t            ds_ystep;
  687.  
  688. // start of a 64*64 tile image 
  689. byte*            ds_source;    
  690.  
  691. // just for profiling
  692. int            dscount;
  693.  
  694.  
  695. //
  696. // Draws the actual span.
  697. // UNUSED.
  698. #ifndef AMIGA
  699. void R_DrawSpan (void) 
  700.     fixed_t        xfrac;
  701.     fixed_t        yfrac; 
  702.     byte*        dest; 
  703.     int            count;
  704.     int            spot; 
  705.      
  706. #ifdef RANGECHECK 
  707.     if (ds_x2 < ds_x1
  708.     || ds_x1<0
  709.     || ds_x2>=SCREENWIDTH  
  710.     || (unsigned)ds_y>SCREENHEIGHT)
  711.     {
  712.     I_Error( "R_DrawSpan: %i to %i at %i",
  713.          ds_x1,ds_x2,ds_y);
  714.     }
  715. //    dscount++; 
  716. #endif 
  717.  
  718.     
  719.     xfrac = ds_xfrac; 
  720.     yfrac = ds_yfrac; 
  721.      
  722.     dest = ylookup[ds_y] + columnofs[ds_x1];
  723.  
  724.     // We do not check for zero spans here?
  725.     count = ds_x2 - ds_x1; 
  726.  
  727.     do 
  728.     {
  729.     // Current texture index in u,v.
  730.     spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  731.  
  732.     // Lookup pixel from flat texture tile,
  733.     //  re-index using light/colormap.
  734.     *dest++ = ds_colormap[ds_source[spot]];
  735.  
  736.     // Next step in u,v.
  737.     xfrac += ds_xstep; 
  738.     yfrac += ds_ystep;
  739.     
  740.     } while (count--); 
  741. #endif
  742.  
  743. //void R_DrawSpan_040 (void)
  744. //{
  745. //  R_DrawSpan ();
  746. //}
  747. //
  748. //void R_DrawSpan_060 (void)
  749. //{
  750. //  R_DrawSpan ();
  751. //}
  752.  
  753. // UNUSED.
  754. // Loop unrolled by 4.
  755. #if 0
  756. void R_DrawSpan (void) 
  757.     unsigned    position, step;
  758.  
  759.     byte*    source;
  760.     byte*    colormap;
  761.     byte*    dest;
  762.     
  763.     unsigned    count;
  764.     usingned    spot; 
  765.     unsigned    value;
  766.     unsigned    temp;
  767.     unsigned    xtemp;
  768.     unsigned    ytemp;
  769.         
  770.     position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
  771.     step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
  772.         
  773.     source = ds_source;
  774.     colormap = ds_colormap;
  775.     dest = ylookup[ds_y] + columnofs[ds_x1];     
  776.     count = ds_x2 - ds_x1 + 1; 
  777.     
  778.     while (count >= 4) 
  779.     { 
  780.     ytemp = position>>4;
  781.     ytemp = ytemp & 4032;
  782.     xtemp = position>>26;
  783.     spot = xtemp | ytemp;
  784.     position += step;
  785.     dest[0] = colormap[source[spot]]; 
  786.  
  787.     ytemp = position>>4;
  788.     ytemp = ytemp & 4032;
  789.     xtemp = position>>26;
  790.     spot = xtemp | ytemp;
  791.     position += step;
  792.     dest[1] = colormap[source[spot]];
  793.     
  794.     ytemp = position>>4;
  795.     ytemp = ytemp & 4032;
  796.     xtemp = position>>26;
  797.     spot = xtemp | ytemp;
  798.     position += step;
  799.     dest[2] = colormap[source[spot]];
  800.     
  801.     ytemp = position>>4;
  802.     ytemp = ytemp & 4032;
  803.     xtemp = position>>26;
  804.     spot = xtemp | ytemp;
  805.     position += step;
  806.     dest[3] = colormap[source[spot]]; 
  807.         
  808.     count -= 4;
  809.     dest += 4;
  810.     } 
  811.     while (count > 0) 
  812.     { 
  813.     ytemp = position>>4;
  814.     ytemp = ytemp & 4032;
  815.     xtemp = position>>26;
  816.     spot = xtemp | ytemp;
  817.     position += step;
  818.     *dest++ = colormap[source[spot]]; 
  819.     count--;
  820.     } 
  821. #endif
  822.  
  823.  
  824. #ifndef AMIGA
  825. //
  826. // Again..
  827. //
  828. void R_DrawSpanLow (void) 
  829.     fixed_t        xfrac;
  830.     fixed_t        yfrac; 
  831.     byte*        dest; 
  832.     int            count;
  833.     int            spot; 
  834.      
  835. #ifdef RANGECHECK 
  836.     if (ds_x2 < ds_x1
  837.     || ds_x1<0
  838.     || ds_x2>=SCREENWIDTH  
  839.     || (unsigned)ds_y>SCREENHEIGHT)
  840.     {
  841.     I_Error( "R_DrawSpan: %i to %i at %i",
  842.          ds_x1,ds_x2,ds_y);
  843.     }
  844. //    dscount++; 
  845. #endif 
  846.      
  847.     xfrac = ds_xfrac; 
  848.     yfrac = ds_yfrac; 
  849.  
  850.     // Blocky mode, need to multiply by 2.
  851.     ds_x1 <<= 1;
  852.     ds_x2 <<= 1;
  853.     
  854.     dest = ylookup[ds_y] + columnofs[ds_x1];
  855.   
  856.     
  857.     count = ds_x2 - ds_x1; 
  858.     do 
  859.     { 
  860.     spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  861.     // Lowres/blocky mode does it twice,
  862.     //  while scale is adjusted appropriately.
  863.     *dest++ = ds_colormap[ds_source[spot]]; 
  864.     *dest++ = ds_colormap[ds_source[spot]];
  865.     
  866.     xfrac += ds_xstep; 
  867.     yfrac += ds_ystep; 
  868.  
  869.     } while (count--); 
  870. }
  871. #endif
  872.  
  873. //
  874. // R_InitBuffer 
  875. // Creats lookup tables that avoid
  876. //  multiplies and other hazzles
  877. //  for getting the framebuffer address
  878. //  of a pixel to draw.
  879. //
  880. void
  881. R_InitBuffer
  882. ( int        width,
  883.   int        height ) 
  884.     int        i, offset;
  885.  
  886.     // Handle resize,
  887.     //  e.g. smaller view windows
  888.     //  with border and/or status bar.
  889.     viewwindowx = (SCREENWIDTH-width) >> 1; 
  890.  
  891.     // Column offset. For windows.
  892.     for (i=0 ; i<width ; i++) 
  893.     columnofs[i] = viewwindowx + i;
  894.  
  895.     // Samw with base row offset.
  896.     if (width == SCREENWIDTH) 
  897.     viewwindowy = 0; 
  898.     else 
  899.     viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1; 
  900.  
  901.     // Preclaculate all row offsets.
  902.     offset = viewwindowy * SCREENWIDTH;
  903.     for (i=0 ; i<height ; i++) {
  904.     ylookup[i] = screens[0] + offset;
  905.         ylookup2[i] = ylookup[i] + viewwindowx;
  906.         offset += SCREENWIDTH;
  907.     }
  908.  
  909.  
  910.  
  911.  
  912. //
  913. // R_FillBackScreen
  914. // Fills the back screen with a pattern
  915. //  for variable screen sizes
  916. // Also draws a beveled edge.
  917. //
  918. void R_FillBackScreen (void) 
  919.     byte*    src;
  920.     byte*    dest; 
  921.     int        x;
  922.     int        y; 
  923.     patch_t*    patch;
  924.  
  925.     // DOOM border patch.
  926.     char    name1[] = "FLOOR7_2";
  927.  
  928.     // DOOM II border patch.
  929.     char    name2[] = "GRNROCK";    
  930.  
  931.     char*    name;
  932.     
  933.     if ((scaledviewwidth == SCREENWIDTH)&&(viewheight==SCREENHEIGHT))
  934.     return;
  935.     
  936.     if ( gamemode == commercial)
  937.     name = name2;
  938.     else
  939.     name = name1;
  940.     
  941.     src = W_CacheLumpName (name, PU_CACHE); 
  942.     dest = screens[1]; 
  943.      
  944.     for (y=0 ; y<SCREENHEIGHT/*-SBARHEIGHT*/ ; y++)
  945.     { 
  946.     for (x=0 ; x<SCREENWIDTH/64 ; x++) 
  947.     { 
  948.         memcpy (dest, src+((y&63)<<6), 64); 
  949.         dest += 64; 
  950.     } 
  951.  
  952.     if (SCREENWIDTH&63) 
  953.     { 
  954.         memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63); 
  955.         dest += (SCREENWIDTH&63); 
  956.     } 
  957.     } 
  958.     if (SCREENWIDTH==scaledviewwidth)
  959.      return;
  960.  
  961.    if ((viewwindowy-8)>=0)
  962.      {
  963.      patch = W_CacheLumpName ("brdr_t",PU_CACHE);
  964.      for (x=0 ; x<scaledviewwidth ; x+=8)
  965.        V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
  966.      }
  967.    if ((viewwindowy+viewheight+8)<(SCREENHEIGHT-SBARHEIGHT))
  968.      {
  969.      patch = W_CacheLumpName ("brdr_b",PU_CACHE);
  970.      for (x=0 ; x<scaledviewwidth ; x+=8)
  971.        V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
  972.      }
  973.    if ((viewwindowx-8)>=0)
  974.      {
  975.      patch = W_CacheLumpName ("brdr_l",PU_CACHE);
  976.      for (y=0 ; y<viewheight ; y+=8)
  977.        V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
  978.      }
  979.    if ((viewwindowx+scaledviewwidth+8)<SCREENWIDTH)
  980.      {
  981.      patch = W_CacheLumpName ("brdr_r",PU_CACHE);
  982.      for (y=0 ; y<viewheight ; y+=8)
  983.        V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
  984.      }
  985.  
  986.     // Draw beveled edge.
  987.     if (((viewwindowx-8)>=0)&&((viewwindowy-8)>=0))
  988.       V_DrawPatch (viewwindowx-8,
  989.          viewwindowy-8,
  990.          1,
  991.          W_CacheLumpName ("brdr_tl",PU_CACHE));
  992.     
  993.     if (((viewwindowx+scaledviewwidth+8)<SCREENWIDTH)&&((viewwindowy-8)>=0))
  994.       V_DrawPatch (viewwindowx+scaledviewwidth,
  995.          viewwindowy-8,
  996.          1,
  997.          W_CacheLumpName ("brdr_tr",PU_CACHE));
  998.  
  999.     if (((viewwindowx-8)>=0)&&((viewwindowy+viewheight+8)<(SCREENHEIGHT-SBARHEIGHT)))
  1000.       V_DrawPatch (viewwindowx-8,
  1001.          viewwindowy+viewheight,
  1002.          1,
  1003.          W_CacheLumpName ("brdr_bl",PU_CACHE));
  1004.     
  1005.     if (((viewwindowx+scaledviewwidth+8)<SCREENWIDTH)&&((viewwindowy+viewheight+8)<(SCREENHEIGHT-SBARHEIGHT)))
  1006.       V_DrawPatch (viewwindowx+scaledviewwidth,
  1007.          viewwindowy+viewheight,
  1008.          1,
  1009.          W_CacheLumpName ("brdr_br",PU_CACHE));
  1010.  
  1011.  
  1012. #if 0
  1013.  
  1014.     if (scaledviewwidth == 320)
  1015.     return;
  1016.     
  1017.     if ( gamemode == commercial)
  1018.     name = name2;
  1019.     else
  1020.     name = name1;
  1021.     
  1022.     src = W_CacheLumpName (name, PU_CACHE); 
  1023.     dest = screens[1]; 
  1024.      
  1025.     for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++) 
  1026.     { 
  1027.     for (x=0 ; x<SCREENWIDTH/64 ; x++) 
  1028.     { 
  1029.         memcpy (dest, src+((y&63)<<6), 64); 
  1030.         dest += 64; 
  1031.     } 
  1032.  
  1033.     if (SCREENWIDTH&63) 
  1034.     { 
  1035.         memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63); 
  1036.         dest += (SCREENWIDTH&63); 
  1037.     } 
  1038.     } 
  1039.     
  1040.     patch = W_CacheLumpName ("brdr_t",PU_CACHE);
  1041.  
  1042.     for (x=0 ; x<scaledviewwidth ; x+=8)
  1043.     V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
  1044.     patch = W_CacheLumpName ("brdr_b",PU_CACHE);
  1045.  
  1046.     for (x=0 ; x<scaledviewwidth ; x+=8)
  1047.     V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
  1048.     patch = W_CacheLumpName ("brdr_l",PU_CACHE);
  1049.  
  1050.     for (y=0 ; y<viewheight ; y+=8)
  1051.     V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
  1052.     patch = W_CacheLumpName ("brdr_r",PU_CACHE);
  1053.  
  1054.     for (y=0 ; y<viewheight ; y+=8)
  1055.     V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
  1056.  
  1057.  
  1058.     // Draw beveled edge. 
  1059.     V_DrawPatch (viewwindowx-8,
  1060.          viewwindowy-8,
  1061.          1,
  1062.          W_CacheLumpName ("brdr_tl",PU_CACHE));
  1063.     
  1064.     V_DrawPatch (viewwindowx+scaledviewwidth,
  1065.          viewwindowy-8,
  1066.          1,
  1067.          W_CacheLumpName ("brdr_tr",PU_CACHE));
  1068.     
  1069.     V_DrawPatch (viewwindowx-8,
  1070.          viewwindowy+viewheight,
  1071.          1,
  1072.          W_CacheLumpName ("brdr_bl",PU_CACHE));
  1073.     
  1074.     V_DrawPatch (viewwindowx+scaledviewwidth,
  1075.          viewwindowy+viewheight,
  1076.          1,
  1077.          W_CacheLumpName ("brdr_br",PU_CACHE));
  1078.  
  1079. #endif
  1080.  
  1081.  
  1082.  
  1083. //
  1084. // Copy a screen buffer.
  1085. //
  1086. void
  1087. R_VideoErase
  1088. ( unsigned    ofs,
  1089.   int        count ) 
  1090.   // LFB copy.
  1091.   // This might not be a good idea if memcpy
  1092.   //  is not optiomal, e.g. byte by byte on
  1093.   //  a 32bit CPU, as GNU GCC/Linux libc did
  1094.   //  at one point.
  1095.     memcpy (screens[0]+ofs, screens[1]+ofs, count); 
  1096.  
  1097.  
  1098. //
  1099. // R_DrawViewBorder
  1100. // Draws the border around the view
  1101. //  for different size windows?
  1102. //
  1103. //void
  1104. //V_MarkRect
  1105. //( int        x,
  1106. //  int        y,
  1107. //  int        width,
  1108. //  int        height ); 
  1109.  
  1110. void R_DrawViewBorder (void) 
  1111.     int        top;
  1112.     int        side,side2;
  1113.     int        ofs;
  1114.     int        i; 
  1115.  
  1116.     //if screenwidth>320, draw stuff around status bar, even if scaledviewwidth==SCREENWIDTH
  1117.     if ((SCREENWIDTH>320)&&(SCREENHEIGHT!=viewheight))
  1118.       {
  1119.       ofs=(SCREENHEIGHT-SBARHEIGHT)*SCREENWIDTH;
  1120.       side=(SCREENWIDTH-320)/2; side2=side*2;
  1121.       R_VideoErase(ofs,side);
  1122.  
  1123.       ofs+=(SCREENWIDTH-side);
  1124.       for (i=1;i<SBARHEIGHT;i++)
  1125.         {
  1126.         R_VideoErase(ofs,side2);
  1127.         ofs+=SCREENWIDTH;
  1128.         }
  1129.       R_VideoErase(ofs,side);
  1130.       }
  1131.  
  1132. //    if (scaledviewwidth == SCREENWIDTH) 
  1133.     if (viewheight>=(SCREENHEIGHT-SBARHEIGHT))
  1134.     return; 
  1135.   
  1136.     top = ((SCREENHEIGHT-SBARHEIGHT)-viewheight)/2; 
  1137.     side = (SCREENWIDTH-scaledviewwidth)/2; 
  1138.  
  1139.     // copy top and one line of left side 
  1140.     R_VideoErase (0, top*SCREENWIDTH+side); 
  1141.  
  1142.     // copy one line of right side and bottom 
  1143.     ofs = (viewheight+top)*SCREENWIDTH-side; 
  1144.     R_VideoErase (ofs, top*SCREENWIDTH+side); 
  1145.  
  1146.     // copy sides using wraparound 
  1147.     ofs = top*SCREENWIDTH + SCREENWIDTH-side; 
  1148.     side <<= 1;
  1149.     
  1150.     for (i=1 ; i<viewheight ; i++) 
  1151.     { 
  1152.     R_VideoErase (ofs, side); 
  1153.     ofs += SCREENWIDTH; 
  1154.     } 
  1155.  
  1156.     // ? 
  1157.     I_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT); 
  1158.  
  1159.  
  1160.